package jobs

import (
	"errors"
	"fmt"
	"os"
	"strconv"

	"github.com/segmentio/ksuid"

	md "gitee.com/countpoison/youbei/models"
	db "gitee.com/countpoison/youbei/utils/database"
	"gitee.com/countpoison/youbei/utils/file"
	"gitee.com/countpoison/youbei/utils/mail"
	rs "gitee.com/countpoison/youbei/utils/rs"
)

//ExecBackup ...
func ExecBackup(log *md.Log) {
	t := log.DBInfo
	if t.DBType == "mysql" {
		//if
		log.Localfilepath, log.Errors = db.MysqlSQLDump(t.Host, t.Port, t.DBname, t.User, t.Password, t.Char, t.SavePath, t.Zippwd)
	} else if t.DBType == "mssql" {
		log.Localfilepath, log.Errors = db.MssqlSQLDump(t.Host, t.DBname, t.User, t.Password, t.SavePath, t.Zippwd)
	} else if t.DBType == "sqlite" {
		log.Localfilepath, log.Errors = db.SqliteSQLDump(t.DBpath, t.SavePath, t.Zippwd)
	} else if t.DBType == "file" {
		log.Localfilepath, log.Errors = filedump.FileDump(t.DBpath, t.SavePath, t.Zippwd)
	} else {
		log.Errors = errors.New("dbtype not found")
	}
	return
}

//ExecRemote ...
func ExecRemote(index int, rlog *md.Rlog, log *md.Log) error {
	var err error
	v := log.RS[index]
	yuancheng := rs.NewRS(v.Host, v.Port, v.Username, v.Password, log.Localfilepath, v.Path)
	if v.Types == "ftp" {
		err = yuancheng.FtpUpload()
	} else if v.Types == "sftp" {
		f, err := yuancheng.NewSftp()
		if err == nil {
			err = f.Upload()
		}
	} else if v.Types == "Yserver" {
		fp, err := yuancheng.ReadBigFile(v.ReLink)
		if err == nil {
			fu := new(md.YsUploadFile)
			fu.ID = ksuid.New().String()
			fu.Lid = rlog.ID
			fu.SrcFilePath = fp.SrcFilePath
			fu.UploadFileServerID = fp.UploadFileServerID
			fu.Size = fp.Size
			fu.PacketNum = fp.PacketNum
			fu.YsPackets = []md.YsPackets{}
			for _, v := range fp.Packets {
				packetlog := md.YsPackets{}
				packetlog.ID = ksuid.New().String()
				packetlog.Yid = fu.ID
				packetlog.Offset = v.Offset
				packetlog.Status = 1
				packetlog.SortID = v.SortID
				packetlog.SrcPacketPath = v.Packetpath
				packetlog.UploadPacketURL = fp.PacketUploadURL + strconv.Itoa(v.SortID)
				fu.YsPackets = append(fu.YsPackets, packetlog)
			}
			err := fu.AddYsFileLog(err)
			if err != nil {
				return err
			}

			file, err := os.OpenFile(fp.SrcFilePath, os.O_RDONLY, os.ModePerm)
			defer file.Close()
			var perr error
			if err != nil {
				perr = err
			}

			for _, v := range fp.Packets {
				var err error
				if perr == nil {
					err = fp.CreatePacket(file, v)
				} else {
					err = perr
				}
				fu.UpdateYspacketLog(fu.ID, v.SortID, err)
			}
		}

	}
	return err
}

//Backup ...
func Backup(tid string, nowreturn bool) error {
	log, err := md.NewLog(tid)

	if err != nil {
		return err
	}

	ExecBackup(log)

	if err := log.Add(); err != nil {
		fmt.Println("log insert failed:", err.Error())
	}

	var reerr error
	for k := range log.RS {
		rlog, err := log.NewRlog(log.RS[k].ID)
		if err != nil {
			return err
		}
		if log.RS[k].ReLink < 1 {
			log.RS[k].ReLink = 1
		}
		if log.RS[k].Types == "ftp" || log.RS[k].Types == "sftp" {
			for i := 1; i <= log.RS[k].ReLink; i++ {
				if reerr = ExecRemote(k, rlog, log); reerr == nil {
					continue
				}
			}
		} else {
			reerr = ExecRemote(k, rlog, log)
		}
		if nowreturn {
			if reerr != nil {
				return reerr
			}
		}
		rlog.Update(reerr)
	}

	return reerr

}

//Jobs ...
func Jobs(i string) func() error {
	return func() error {
		err := Backup(i, false)
		if err != nil {
			m := new(mail.MailConn)
			m.SendMail("备份失败", err.Error())
		}
		return nil
	}
}
